﻿using System;
using Autodesk.Revit.DB;

namespace YJKExcelFormTool.Utilities
{
	public class MapEdge
	{
		public ElementId ComponentId
		{
			get
			{
				return this.m_ComponentId;
			}
		}

		public bool IsPositiveDirection
		{
			get
			{
				return this.m_PositiveDirection;
			}
		}

		public bool IsArcEdge
		{
			get
			{
				return !Geometry.IsEqual(this.m_Bulge, 0.0);
			}
		}

		public XYZ StartPoint
		{
			get
			{
				return this.m_ptStart;
			}
		}

		public XYZ EndPoint
		{
			get
			{
				return this.m_ptEnd;
			}
		}

		public XYZ PositiveStartPoint
		{
			get
			{
				return this.m_ptPositiveStart;
			}
		}

		public XYZ PositiveEndPoint
		{
			get
			{
				return this.m_ptPositiveEnd;
			}
		}

		public XYZ NegativeStartPoint
		{
			get
			{
				return this.m_ptNegativeStart;
			}
		}

		public XYZ NegativeEndPoint
		{
			get
			{
				return this.m_ptNegativeEnd;
			}
		}

		public double Bulge
		{
			get
			{
				return this.m_Bulge;
			}
		}

		public double PositiveHalfWidth
		{
			get
			{
				double result;
				if (this.IsArcEdge)
				{
					XYZ xyz = null;
					Geometry.GetCenterWithBulge(this.m_ptStart, this.m_ptEnd, this.m_Bulge, ref xyz);
					result = this.m_ptPositiveStart.DistanceTo(xyz) - this.Radius;
				}
				else
				{
					result = Geometry.CalculateFootPoint(this.m_ptStart, this.m_ptEnd, this.m_ptPositiveStart).DistanceTo(this.m_ptPositiveStart);
				}
				return result;
			}
		}

		public double NegativeHalfWidth
		{
			get
			{
				double result;
				if (this.IsArcEdge)
				{
					XYZ xyz = null;
					Geometry.GetCenterWithBulge(this.m_ptStart, this.m_ptEnd, this.m_Bulge, ref xyz);
					result = this.Radius - this.m_ptNegativeStart.DistanceTo(xyz);
				}
				else
				{
					result = Geometry.CalculateFootPoint(this.m_ptStart, this.m_ptEnd, this.m_ptNegativeStart).DistanceTo(this.m_ptNegativeStart);
				}
				return result;
			}
		}

		public XYZ Center
		{
			get
			{
				if (Geometry.IsEqual(this.m_Bulge, 0.0))
				{
					return null;
				}
				XYZ result = null;
				Geometry.GetCenterWithBulge(this.m_ptStart, this.m_ptEnd, this.m_Bulge, ref result);
				return result;
			}
		}

		public double Radius
		{
			get
			{
				if (Geometry.IsEqual(this.m_Bulge, 0.0))
				{
					return double.MaxValue;
				}
				double result = 0.0;
				Geometry.GetRadiusWithBulge(this.m_ptStart, this.m_ptEnd, this.m_Bulge, ref result);
				return result;
			}
		}

		public bool SameAs(MapEdge rhs)
		{
			return this.ComponentId.IntegerValue.CompareTo(rhs.ComponentId.IntegerValue) != 0 && ((this.m_ptStart.IsAlmostEqualTo(rhs.m_ptStart, 0.0001) && this.m_ptEnd.IsAlmostEqualTo(rhs.m_ptEnd, 0.0001) && Geometry.IsEqual(this.m_Bulge, rhs.m_Bulge)) || (this.m_ptStart.IsAlmostEqualTo(rhs.m_ptEnd, 0.0001) && this.m_ptEnd.IsAlmostEqualTo(rhs.m_ptStart, 0.0001) && Geometry.IsEqual(-this.m_Bulge, rhs.m_Bulge)));
		}

		private MapEdge._tagPositionType TestPointPositionType(XYZ ptCurNodePos)
		{
			double val = this.m_ptStart.DistanceTo(ptCurNodePos);
			double val2 = this.m_ptEnd.DistanceTo(ptCurNodePos);
			if (Geometry.LessThan(val, val2))
			{
				return MapEdge._tagPositionType._StartNode;
			}
			if (Geometry.GreaterThan(val, val2))
			{
				return MapEdge._tagPositionType._EndNode;
			}
			return MapEdge._tagPositionType._OtherPoint;
		}

		public bool GetAngle(XYZ ptCurNodePos, ref double curAngle)
		{
			MapEdge._tagPositionType tagPositionType = this.TestPointPositionType(ptCurNodePos);
			if (tagPositionType == MapEdge._tagPositionType._StartNode)
			{
				if (!this.IsArcEdge)
				{
					curAngle = Geometry.getAngle(this.m_ptStart, this.m_ptEnd);
				}
				else if (Geometry.LessThan(this.m_Bulge, 0.0))
				{
					XYZ ptCenter = new XYZ(0.0, 0.0, 0.0);
					Geometry.GetCenterWithBulge(this.m_ptStart, this.m_ptEnd, this.m_Bulge, ref ptCenter);
					curAngle = Geometry.getAngle(ptCenter, this.m_ptStart);
					curAngle = Geometry.formatAngle(curAngle - Math.PI*.5);
				}
				else
				{
					XYZ ptCenter2 = new XYZ(0.0, 0.0, 0.0);
					Geometry.GetCenterWithBulge(this.m_ptStart, this.m_ptEnd, this.m_Bulge, ref ptCenter2);
					curAngle = Geometry.getAngle(ptCenter2, this.m_ptStart);
					curAngle = Geometry.formatAngle(curAngle + Math.PI*.5);
				}
				return true;
			}
			if (tagPositionType == MapEdge._tagPositionType._EndNode)
			{
				if (!this.IsArcEdge)
				{
					curAngle = Geometry.getAngle(this.m_ptEnd, this.m_ptStart);
				}
				else if (Geometry.LessThan(this.m_Bulge, 0.0))
				{
					XYZ ptCenter3 = new XYZ(0.0, 0.0, 0.0);
					Geometry.GetCenterWithBulge(this.m_ptStart, this.m_ptEnd, this.m_Bulge, ref ptCenter3);
					curAngle = Geometry.getAngle(ptCenter3, this.m_ptEnd);
					curAngle = Geometry.formatAngle(curAngle + Math.PI*.5);
				}
				else
				{
					XYZ ptCenter4 = new XYZ(0.0, 0.0, 0.0);
					Geometry.GetCenterWithBulge(this.m_ptStart, this.m_ptEnd, this.m_Bulge, ref ptCenter4);
					curAngle = Geometry.getAngle(ptCenter4, this.m_ptEnd);
					curAngle = Geometry.formatAngle(curAngle - Math.PI*.5);
				}
				return true;
			}
			return false;
		}

		public bool GetWinding(XYZ ptCurNodePos, ref int winding)
		{
			MapEdge._tagPositionType tagPositionType = this.TestPointPositionType(ptCurNodePos);
			if (tagPositionType == MapEdge._tagPositionType._StartNode)
			{
				winding = 1;
				if (!this.IsArcEdge)
				{
					winding = 0;
				}
				if (Geometry.LessThan(this.m_Bulge, 0.0))
				{
					winding = -1;
				}
				return true;
			}
			if (tagPositionType == MapEdge._tagPositionType._EndNode)
			{
				winding = -1;
				if (!this.IsArcEdge)
				{
					winding = 0;
				}
				if (Geometry.LessThan(this.m_Bulge, 0.0))
				{
					winding = 1;
				}
				return true;
			}
			return false;
		}

		public void SetIsPositiveDirection(XYZ ptCurNodePos)
		{
			MapEdge._tagPositionType tagPositionType = this.TestPointPositionType(ptCurNodePos);
			if (tagPositionType == MapEdge._tagPositionType._StartNode)
			{
				this.m_PositiveDirection = true;
				return;
			}
			if (tagPositionType == MapEdge._tagPositionType._EndNode)
			{
				this.m_PositiveDirection = false;
			}
		}

		public XYZ CurStartPoint(XYZ ptCurNodePos)
		{
			MapEdge._tagPositionType tagPositionType = this.TestPointPositionType(ptCurNodePos);
			if (tagPositionType == MapEdge._tagPositionType._StartNode)
			{
				return this.m_ptStart;
			}
			if (tagPositionType == MapEdge._tagPositionType._EndNode)
			{
				return this.m_ptEnd;
			}
			return null;
		}

		public XYZ CurEndPoint(XYZ ptCurNodePos)
		{
			MapEdge._tagPositionType tagPositionType = this.TestPointPositionType(ptCurNodePos);
			if (tagPositionType == MapEdge._tagPositionType._StartNode)
			{
				return this.m_ptEnd;
			}
			if (tagPositionType == MapEdge._tagPositionType._EndNode)
			{
				return this.m_ptStart;
			}
			return null;
		}

		public double CurBulge(XYZ ptCurNodePos)
		{
			double result = 0.0;
			if (!this.IsArcEdge)
			{
				return result;
			}
			MapEdge._tagPositionType tagPositionType = this.TestPointPositionType(ptCurNodePos);
			if (tagPositionType == MapEdge._tagPositionType._StartNode)
			{
				result = this.m_Bulge;
			}
			else if (tagPositionType == MapEdge._tagPositionType._EndNode)
			{
				result = -this.m_Bulge;
			}
			return result;
		}

		public XYZ CurPositiveStartPoint(XYZ ptCurNodePos)
		{
			MapEdge._tagPositionType tagPositionType = this.TestPointPositionType(ptCurNodePos);
			if (tagPositionType == MapEdge._tagPositionType._StartNode)
			{
				return this.m_ptPositiveStart;
			}
			if (tagPositionType == MapEdge._tagPositionType._EndNode)
			{
				return this.m_ptNegativeEnd;
			}
			return null;
		}

		public XYZ CurPositiveEndPoint(XYZ ptCurNodePos)
		{
			MapEdge._tagPositionType tagPositionType = this.TestPointPositionType(ptCurNodePos);
			if (tagPositionType == MapEdge._tagPositionType._StartNode)
			{
				return this.m_ptPositiveEnd;
			}
			if (tagPositionType == MapEdge._tagPositionType._EndNode)
			{
				return this.m_ptNegativeStart;
			}
			return null;
		}

		public bool SetCurPositiveStartPoint(XYZ ptCurNodePos, XYZ ptNewPos)
		{
			MapEdge._tagPositionType tagPositionType = this.TestPointPositionType(ptCurNodePos);
			if (tagPositionType == MapEdge._tagPositionType._StartNode)
			{
				this.m_ptPositiveStart = ptNewPos;
				return true;
			}
			if (tagPositionType == MapEdge._tagPositionType._EndNode)
			{
				this.m_ptNegativeEnd = ptNewPos;
				return true;
			}
			return false;
		}

		public bool SetCurPositiveEndPoint(XYZ ptCurNodePos, XYZ ptNewPos)
		{
			MapEdge._tagPositionType tagPositionType = this.TestPointPositionType(ptCurNodePos);
			if (tagPositionType == MapEdge._tagPositionType._StartNode)
			{
				this.m_ptPositiveEnd = ptNewPos;
				return true;
			}
			if (tagPositionType == MapEdge._tagPositionType._EndNode)
			{
				this.m_ptNegativeStart = ptNewPos;
				return true;
			}
			return false;
		}

		public XYZ CurNegativeStartPoint(XYZ ptCurNodePos)
		{
			MapEdge._tagPositionType tagPositionType = this.TestPointPositionType(ptCurNodePos);
			if (tagPositionType == MapEdge._tagPositionType._StartNode)
			{
				return this.m_ptNegativeStart;
			}
			if (tagPositionType == MapEdge._tagPositionType._EndNode)
			{
				return this.m_ptPositiveEnd;
			}
			return null;
		}

		public XYZ CurNegativeEndPoint(XYZ ptCurNodePos)
		{
			MapEdge._tagPositionType tagPositionType = this.TestPointPositionType(ptCurNodePos);
			if (tagPositionType == MapEdge._tagPositionType._StartNode)
			{
				return this.m_ptNegativeEnd;
			}
			if (tagPositionType == MapEdge._tagPositionType._EndNode)
			{
				return this.m_ptPositiveStart;
			}
			return null;
		}

		public bool SetCurNegativeStartPoint(XYZ ptCurNodePos, XYZ ptNewPos)
		{
			MapEdge._tagPositionType tagPositionType = this.TestPointPositionType(ptCurNodePos);
			if (tagPositionType == MapEdge._tagPositionType._StartNode)
			{
				this.m_ptNegativeStart = ptNewPos;
				return true;
			}
			if (tagPositionType == MapEdge._tagPositionType._EndNode)
			{
				this.m_ptPositiveEnd = ptNewPos;
				return true;
			}
			return false;
		}

		public bool SetCurNegativeEndPoint(XYZ ptCurNodePos, XYZ ptNewPos)
		{
			MapEdge._tagPositionType tagPositionType = this.TestPointPositionType(ptCurNodePos);
			if (tagPositionType == MapEdge._tagPositionType._StartNode)
			{
				this.m_ptNegativeEnd = ptNewPos;
				return true;
			}
			if (tagPositionType == MapEdge._tagPositionType._EndNode)
			{
				this.m_ptPositiveStart = ptNewPos;
				return true;
			}
			return false;
		}

		public MapEdge(MapEdge rhs)
		{
			this.m_ComponentId = rhs.m_ComponentId;
			this.m_ptStart = rhs.m_ptStart;
			this.m_ptEnd = rhs.m_ptEnd;
			this.m_Bulge = rhs.m_Bulge;
			this.m_ptPositiveStart = rhs.m_ptPositiveStart;
			this.m_ptPositiveEnd = rhs.m_ptPositiveEnd;
			this.m_ptNegativeStart = rhs.m_ptNegativeStart;
			this.m_ptNegativeEnd = rhs.m_ptNegativeEnd;
			this.m_PositiveDirection = rhs.m_PositiveDirection;
		}

		public MapEdge(ElementId componentId, XYZ ptStart, XYZ ptEnd, double bulge, XYZ ptPositiveStart, XYZ ptPositiveEnd, XYZ ptNegativeStart, XYZ ptNegativeEnd, bool positiveDirection)
		{
			this.m_ComponentId = componentId;
			this.m_ptStart = ptStart;
			this.m_ptEnd = ptEnd;
			this.m_Bulge = bulge;
			this.m_ptPositiveStart = ptPositiveStart;
			this.m_ptPositiveEnd = ptPositiveEnd;
			this.m_ptNegativeStart = ptNegativeStart;
			this.m_ptNegativeEnd = ptNegativeEnd;
			this.m_PositiveDirection = positiveDirection;
		}

		public static MapEdge NewEdge(ElementId id, XYZ ptStart, XYZ ptEnd, double posiHalfWidth, double negaHalfWidth)
		{
			XYZ xyz = Geometry.RotateTo((ptEnd - ptStart).Normalize(), -Math.PI*.5, XYZ.BasisZ);
			XYZ xyz2 = xyz.Negate();
			xyz *= posiHalfWidth;
			xyz2 *= negaHalfWidth;
			XYZ ptPositiveStart = ptStart + xyz;
			XYZ ptPositiveEnd = ptEnd + xyz;
			XYZ ptNegativeStart = ptStart + xyz2;
			XYZ ptNegativeEnd = ptEnd + xyz2;
			return new MapEdge(id, ptStart, ptEnd, 0.0, ptPositiveStart, ptPositiveEnd, ptNegativeStart, ptNegativeEnd, true);
		}

		public static MapEdge NewEdge(ElementId id, XYZ ptStart, XYZ ptEnd, XYZ ptCenter, XYZ normal, double posiHalfWidth, double negaHalfWidth)
		{
			if (!normal.IsAlmostEqualTo(XYZ.BasisZ, 0.0001))
			{
				XYZ xyz = ptStart;
				ptStart = ptEnd;
				ptEnd = xyz;
			}
			double bulge = Geometry.GetBulge(ptStart, ptEnd, ptCenter, true);
			double num = ptCenter.DistanceTo(ptStart);
			XYZ xyz2 = (ptStart - ptCenter).Normalize() * (num + posiHalfWidth);
			XYZ xyz3 = (ptEnd - ptCenter).Normalize() * (num + posiHalfWidth);
			XYZ xyz4 = (ptStart - ptCenter).Normalize() * (num - negaHalfWidth);
			XYZ xyz5 = (ptEnd - ptCenter).Normalize() * (num - negaHalfWidth);
			XYZ ptPositiveStart = ptCenter + xyz2;
			XYZ ptPositiveEnd = ptCenter + xyz3;
			XYZ ptNegativeStart = ptCenter + xyz4;
			XYZ ptNegativeEnd = ptCenter + xyz5;
			return new MapEdge(id, ptStart, ptEnd, bulge, ptPositiveStart, ptPositiveEnd, ptNegativeStart, ptNegativeEnd, true);
		}

		private ElementId m_ComponentId;

		private XYZ m_ptStart;

		private XYZ m_ptEnd;

		private double m_Bulge;

		private XYZ m_ptPositiveStart;

		private XYZ m_ptPositiveEnd;

		private XYZ m_ptNegativeStart;

		private XYZ m_ptNegativeEnd;

		private bool m_PositiveDirection = true;

		private enum _tagPositionType
		{
			_StartNode,
			_EndNode,
			_OtherPoint
		}
	}
}
